/*
 * Settings.h
 *
 *  Created on: Jan 8, 2011
 *      Author: Kevin Mueller
 */

#ifndef SETTINGS_H_
#define SETTINGS_H_

#include "Main.h"
#include "Helpers.h"
#include "PositioningSystem.h"
#include "SearchService.h"

#include <QObject>
#include <QGeoCoordinate>
#include <QAbstractListModel>

//class QAbstractSlider;
class QString;
class QSettings;
//class QXmlStreamReader;
//class QXmlStreamWriter;
class AbstractSetting;
class RecentPlaces;
class CenterPosition;
class MapFileLocation;

class ExtendedGeoPositionInfo;

class Settings: public QObject {
Q_OBJECT

public:
	Settings(QObject *parent = 0);
	~Settings();
	AbstractSetting* getAnnouncement() const;
	AbstractSetting* getArrival() const;
	AbstractSetting* getAutoCenter() const;
	AbstractSetting* getAvoidHighways() const;
	AbstractSetting* getAvoidTollroads() const;
	AbstractSetting* getColors() const;
	AbstractSetting* getDegreeFormat() const;
	AbstractSetting* getGPSStatus() const;
	AbstractSetting* getLanguage() const;
	AbstractSetting* getOrientation() const;
	AbstractSetting* getPollingInterval() const;
	AbstractSetting* getReducedPollingInterval() const;
	AbstractSetting* getRotateMap() const;
	AbstractSetting* getRouteCalculation() const;
	AbstractSetting* getShadowMapSize() const;
	AbstractSetting* getShowCompass() const;
	AbstractSetting* getShowPOI() const;
	AbstractSetting* getShowScale() const;
	AbstractSetting* getShowVelocityVector() const;
	AbstractSetting* getSpeedLimit() const;
	AbstractSetting* getUnblank() const;
	AbstractSetting* getUnit() const;
	AbstractSetting* getVolumeKeys() const;
	AbstractSetting* getZoomLevel() const;
	RecentPlaces* getRecentPlaces() const;
	CenterPosition* getCenterPosition() const;
	MapFileLocation* getMapFileLocation() const;
	bool save() const;
	bool load() const;

signals:
void settingsChanged();

public slots:
void changed();

private:
	static const int AUTOCENTER = 0;
	static const int LANGUAGE = 1;
	static const int ORIENTATION = 2;
	static const int UNBLANK = 3;
	static const int DEGREEFORMAT = 4;
	static const int SPEEDLIMIT = 5;
	static const int ANNOUNCEMENTS = 6;
	static const int ROUTECALCULATION = 7;
	static const int UNIT = 8;
	static const int ARRIVAL = 9;
	static const int COLORS = 10;
	static const int GPSSTATUS = 11;
	static const int POLLING = 12;
	static const int REDUCEDPOLLING = 13;
	static const int SHOWCOMPASS = 14;
	static const int SHOWPOI = 15;
	static const int SHOWSCALE = 16;
	static const int SHOWVELOCITY = 17;
	static const int AVOIDHIGHWAYS = 18;
	static const int AVOIDTOLLROADS = 19;
	static const int ZOOMLEVEL = 20;
	static const int VOLUMEKEYS = 21;
	static const int ROTATEMAP = 22;
	static const int SHADOWMAPSIZE = 23;

	static const int NUM = 24;

	AbstractSetting* settings[NUM];

	RecentPlaces* recentPlaces;
	CenterPosition* center;
	MapFileLocation* mapfileloc;
};

class MapFileLocation {
public:
	MapFileLocation();
	void set(QString &s);
	QString get() const;
	void save(QSettings& settings) const;
	void load(QSettings& settings);
private:
	QString file;
};

class CenterPosition: public QtMobility::QGeoCoordinate {
public:
	CenterPosition();
	void setValue(QGeoCoordinate &c);
	void save(QSettings& settings) const;
	void load(QSettings& settings);
};

class RecentPlaces: public QObject {
Q_OBJECT

public:
	RecentPlaces(QObject* parent = 0);
	~RecentPlaces();
	void
	add(const QString& label, const QtMobility::QGeoCoordinate& coordinate);
	void add(const LabeledCoordinate& place);

	int size() const;
	LabeledCoordinate get(int i) const;
	//	void getAll() const;
	void save(QSettings& settings) const;
	void load(QSettings& settings);

	QAbstractListModel* model(QObject* parent = 0);

private:
	static const int MAX = 10;
	int iSize;

	//	void add(LabeledCoordinate* place);
	LabeledCoordinate list[MAX];

public:
	class RecentPlacesModel: public QAbstractListModel, public ISearchModel {

	public:
		RecentPlacesModel(RecentPlaces* places, QObject* parent = 0);
		int rowCount(const QModelIndex &parent = QModelIndex()) const;
		QVariant data(const QModelIndex &index, int role) const;
		LabeledCoordinate get(int id) const;
		QVariant headerData(int section, Qt::Orientation orientation, int role =
				Qt::DisplayRole) const;

		RecentPlaces* data() const;

		//	Qt::ItemFlags flags(const QModelIndex &index) const;
		//	bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);

		//	bool insertRows(int position, int rows, const QModelIndex &index = QModelIndex());
		//	bool removeRows(int position, int rows, const QModelIndex &index = QModelIndex());

	private:
		RecentPlaces* _data;
	};
};

class AbstractSetting: public QObject {
Q_OBJECT

public:
	AbstractSetting(QString name, int min, int cnt, QObject *parent = 0);
	int getMinimum() const;
	int getMaximum() const;
	int getCurrent() const;
	virtual const char* getDescription(int i) = 0;
	virtual void save(QSettings& settings) const;
	virtual void load(QSettings& settings);

signals:
void settingChanged(AbstractSetting *s);

public slots:
virtual void setCurrent(int c);

protected:
	void setDefault(int c);

private:

	QString ident;
	int minimum;
	int count;
	int current;
	int defaultValue;
};

class Announcement: public AbstractSetting {

private:
	static const int NUM = 4;
	const char* values[NUM];

public:
	static const int DISABLED = 0;
	static const int NECESSARY = 1;
	static const int MEDIUM = 2;
	static const int MUCH = 3;

	Announcement(QObject *parent = 0) :
		AbstractSetting("announcement", 0, NUM, parent) {

		setDefault(MUCH);

		int i = 0;
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "Off");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "Only necessary");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "Medium");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting",
				"As much as possible");
	}

	virtual const char* getDescription(int i);

	void save();
	void load();
};

class Arrival: public AbstractSetting {

private:
	static const int NUM = 2;
	const char* values[NUM];

public:
	static const int ARRIVAL = 0;
	static const int DRIVING = 1;

	Arrival(QObject *parent = 0) :
		AbstractSetting("arrival", 0, NUM, parent) {

		setDefault(ARRIVAL);

		int i = 0;
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "Arrival time");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "Driving time");
	}

	virtual const char* getDescription(int i);

	void save();
	void load();
};

#include <QtCore>

class AutoCenter: public AbstractSetting {
Q_OBJECT

private:
	static const int NUM = 5;
	const char* values[NUM];

signals:
void updatePosition(const QtMobility::QGeoCoordinate&);

private slots:
void calcRepositioning(const ExtendedGeoPositionInfo *posinfo);

public:
	static const int DISABLED = 0;
	static const int EVERYTIME = 1;
	static const int FASTER_5 = 2;
	static const int FASTER_10 = 3;
	static const int FASTER_15 = 4;

	AutoCenter(QObject *parent = 0) :
		AbstractSetting("auto-center", 0, NUM, parent) {

		const Main &main = Main::getInstance();
		connect(&main.getPositioningSystem(), SIGNAL(updated(const ExtendedGeoPositionInfo *)), this, SLOT(calcRepositioning(const ExtendedGeoPositionInfo *)));

		setDefault(FASTER_10);

		int i = 0;
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "Disabled");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "Everytime");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting",
				"Moving faster than 5 km/h");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting",
				"Moving faster than 10 km/h");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting",
				"Moving faster than 15 km/h");
	}

	virtual const char* getDescription(int i);

	void save();
	void load();
};

class AvoidHighways: public AbstractSetting {

private:
	static const int NUM = 2;

public:
	static const int DISABLED = 0;
	static const int ENABLED = 1;

	AvoidHighways(QObject *parent = 0) :
		AbstractSetting("avoid-highways", 0, NUM - 1, parent) {

		setDefault(DISABLED);
	}

	virtual const char* getDescription(int i);

	void save();
	void load();
};

class AvoidTollroads: public AbstractSetting {

private:
	static const int NUM = 2;

public:
	static const int DISABLED = 0;
	static const int ENABLED = 1;

	AvoidTollroads(QObject *parent = 0) :
		AbstractSetting("avoid-toll", 0, NUM - 1, parent) {

		setDefault(DISABLED);
	}

	virtual const char* getDescription(int i);

	void save();
	void load();
};

class Colors: public AbstractSetting {

private:
	static const int NUM = 3;
	const char* values[NUM];

public:
	static const int AUTOMATIC = 0;
	static const int DAY = 1;
	static const int NIGHT = 1;

	Colors(QObject *parent = 0) :
		AbstractSetting("colors", 0, NUM - 1, parent) {

		setDefault(AUTOMATIC);

		int i = 0;
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "Automatic");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "Day mode");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "Night mode");
	}

	virtual const char* getDescription(int i);

	void save();
	void load();
};

class GPSStatus: public AbstractSetting {

private:
	static const int NUM = 2;
	const char* values[NUM];

public:
	static const int DISABLED = 0;
	static const int ENABLED = 1;

	GPSStatus(QObject *parent = 0) :
		AbstractSetting("gps-status", 0, NUM - 1, parent) {

		setDefault(ENABLED);

		int i = 0;
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "disabled");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "enabled");
	}

	virtual const char* getDescription(int i);

	void save();
	void load();
};

class DisplayOrientation: public AbstractSetting {

private:
	static const int NUM = 3;
	const char* values[NUM];

public:
	static const int AUTOMATIC = 0;
	static const int LANDSCAPE = 1;
	static const int PORTRAIT = 2;

	DisplayOrientation(QObject *parent = 0) :
		AbstractSetting("orientation", 0, NUM - 1, parent) {

		setDefault(AUTOMATIC);

		int i = 0;
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "Automatic");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "Landscape");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "Portrait");
	}

	virtual const char* getDescription(int i);

	void save();
	void load();
};

class DegreeFormat: public AbstractSetting {

private:
	static const int NUM = 6;
	const char* values[NUM];

public:
	static const int DEGREES = 0;
	static const int DEGREES_MINUTES = 1;
	static const int DEGREES_MINUTES_SECONDS = 2;
	static const int DEGREES_HEMISPHERE = 3;
	static const int DEGREES_MINUTES_HEMISPHERE = 4;
	static const int DEGREES_MINUTES_SECONDS_HEMISPHERE = 5;

	static QtMobility::QGeoCoordinate::CoordinateFormat getQtFormatIdent(int i) {
		switch (i) {
		case DegreeFormat::DEGREES:
			return QtMobility::QGeoCoordinate::Degrees;

		case DegreeFormat::DEGREES_MINUTES:
			return QtMobility::QGeoCoordinate::DegreesMinutes;

		case DegreeFormat::DEGREES_MINUTES_SECONDS:
			return QtMobility::QGeoCoordinate::DegreesMinutesSeconds;

		case DegreeFormat::DEGREES_HEMISPHERE:
			return QtMobility::QGeoCoordinate::DegreesWithHemisphere;

		case DegreeFormat::DEGREES_MINUTES_HEMISPHERE:
			return QtMobility::QGeoCoordinate::DegreesMinutesWithHemisphere;

		case DegreeFormat::DEGREES_MINUTES_SECONDS_HEMISPHERE:
			return QtMobility::QGeoCoordinate::DegreesMinutesSecondsWithHemisphere;

		}
		return QtMobility::QGeoCoordinate::Degrees;
	}

	DegreeFormat(QObject *parent = 0) :
		AbstractSetting("degree", 0, NUM, parent) {

		setDefault(DEGREES);

		int i = 0;
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "-dd.ddddd°");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "-dd°mm.mmm'");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "-dd°mm'ss.s\"");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "-dd.ddddd° S");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "-dd°mm.mmm' S");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "-dd°mm'ss.s\" S");
	}

	virtual const char* getDescription(int i);

	void save();
	void load();
};

class Language: public AbstractSetting {

public:
	static const int ENGLISH = 0;
	static const int GERMAN = 1;

private:
	static const int NUM = 2;
	static const int DEFAULT = Language::ENGLISH;

	static const char* getLocale(int i) {
		switch (i) {
		case Language::ENGLISH:
			return "en";
			break;
		case Language::GERMAN:
			return "de";
			break;
		}
		return getLocale(DEFAULT);
	}

	const char* values[NUM];

public:
	static const char* getLocale(Language* lang) {
		return getLocale(lang->getCurrent());
	}

	Language(QObject *parent = 0) :
		AbstractSetting("language", 0, NUM, parent) {

		setDefault(DEFAULT);

		int i = 0;
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "English");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "Deutsch");
	}

	virtual const char* getDescription(int i);

	void save();
	void load();
};

class PollingInterval: public AbstractSetting {

private:
	char *buf;

public:

	PollingInterval(QObject *parent = 0) :
		AbstractSetting("polling", 1, 10, parent) {

		buf = new char[10];

		setDefault(1);
	}

	~PollingInterval() {
		delete buf;
	}

	virtual const char* getDescription(int i);

	void save();
	void load();
};

class ReducedPollingInterval: public AbstractSetting {

private:
	char *buf;

public:
	ReducedPollingInterval(QObject *parent = 0) :
		AbstractSetting("reduced-polling", 0, 10, parent) {

		buf = new char[10];

		setDefault(0);
	}

	~ReducedPollingInterval() {
		delete buf;
	}

	virtual const char* getDescription(int i);

	void save();
	void load();
};

class RotateMap: public AbstractSetting {

private:
	static const int NUM = 2;

public:
	static const int DISABLED = 0;
	static const int ENABLED = 1;

	RotateMap(QObject *parent = 0) :
		AbstractSetting("rotatemap", 0, NUM - 1, parent) {

		setDefault(DISABLED);
	}

	virtual const char* getDescription(int i);

	void save();
	void load();
};

class RouteCalculation: public AbstractSetting {

private:
	static const int NUM = 2;
	const char* values[NUM];

public:
	static const int SHORTEST = 0;
	static const int FASTEST = 1;

	RouteCalculation(QObject *parent = 0) :
		AbstractSetting("routecalculation", 0, NUM, parent) {

		setDefault(FASTEST);

		int i = 0;
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "Shortest");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "Fastest");
	}

	virtual const char* getDescription(int i);

	void save();
	void load();
};

class ShadowMapSize: public AbstractSetting {

private:
	static const int NUM = 3;
	const char* values[NUM];

public:
	static const int PERFORMANCE = 0;
	static const int OPTIMIZED = 1;
	static const int VISIBILENESS = 2;

	ShadowMapSize(QObject *parent = 0) :
		AbstractSetting("showmapsize", 0, NUM - 1, parent) {

		setDefault(OPTIMIZED);

		int i = 0;
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "Performant");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "Optimized");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "Visibleness");
	}

	virtual const char* getDescription(int i);

	void save();
	void load();
};

class ShowCompass: public AbstractSetting {

private:
	static const int NUM = 2;

public:
	static const int DISABLED = 0;
	static const int ENABLED = 1;

	ShowCompass(QObject *parent = 0) :
		AbstractSetting("compass", 0, NUM - 1, parent) {

		setDefault(ENABLED);
	}

	virtual const char* getDescription(int i);

	void save();
	void load();
};

class ShowScale: public AbstractSetting {

private:
	static const int NUM = 2;

public:
	static const int DISABLED = 0;
	static const int ENABLED = 1;

	ShowScale(QObject *parent = 0) :
		AbstractSetting("scale", 0, NUM - 1, parent) {

		setDefault(ENABLED);
	}

	virtual const char* getDescription(int i);

	void save();
	void load();
};

class ShowPOI: public AbstractSetting {

private:
	static const int NUM = 2;

public:
	static const int DISABLED = 0;
	static const int ENABLED = 1;

	ShowPOI(QObject *parent = 0) :
		AbstractSetting("poi", 0, NUM - 1, parent) {

		setDefault(ENABLED);
	}

	virtual const char* getDescription(int i);

	void save();
	void load();
};

class ShowVelocityVector: public AbstractSetting {

private:
	static const int NUM = 2;

public:
	static const int DISABLED = 0;
	static const int ENABLED = 1;

	ShowVelocityVector(QObject *parent = 0) :
		AbstractSetting("velocity", 0, NUM - 1, parent) {

		setDefault(ENABLED);
	}

	virtual const char* getDescription(int i);

	void save();
	void load();
};

class SpeedLimit: public AbstractSetting {

private:
	static const int NUM = 3;
	const char* values[NUM];

public:
	static const int DISABLED = 0;
	static const int NAVIGATION = 1;
	static const int EVERYTIME = 2;

	SpeedLimit(QObject *parent = 0) :
		AbstractSetting("speed-limit", 0, NUM, parent) {

		setDefault(EVERYTIME);

		int i = 0;
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "Disabled");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "During Navigation");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "Everytime");
	}

	virtual const char* getDescription(int i);

	void save();
	void load();
};

class Unblank: public AbstractSetting {

private:
	static const int NUM = 7;
	const char* values[NUM];

public:
	static const int CONNECTED = 0;
	static const int MOVING = 1;
	static const int MOVING_FULL = 2;
	static const int NAVIGATION = 3;
	static const int NAVIGATION_FULL = 4;
	static const int WAYPOINT = 5;
	static const int NEVER = 6;

	Unblank(QObject *parent = 0) :
		AbstractSetting("unblank", 0, NUM, parent) {

		setDefault(CONNECTED);

		int i = 0;
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "Connected to GPS");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "Moving");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting",
				"Moving (Fullscreen)");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "During Navigation");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting",
				"During Navigation (Fullscreen)");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting",
				"Approaching Waypoint");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "Never");
	}

	virtual const char* getDescription(int i);

	void save();
	void load();
};

class Unit: public AbstractSetting {

private:
	static const int NUM = 3;
	const char* values[NUM];

public:
	static const int MS = 0;
	static const int KMH = 1;
	static const int MH = 2;

	Unit(QObject *parent = 0) :
		AbstractSetting("unit", 0, NUM, parent) {

		setDefault(KMH);

		int i = 0;
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "m/s");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "km/h");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "M/h");
	}

	virtual const char* getDescription(int i);

	void save();
	void load();
};

class VolumeKeys: public AbstractSetting {

private:
	static const int NUM = 2;
	const char* values[NUM];

public:
	static const int VOLUME = 0;
	static const int ZOOMING = 1;

	VolumeKeys(QObject *parent = 0) :
		AbstractSetting("volumekeys", 0, NUM, parent) {

		setDefault(VOLUME);

		int i = 0;
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "Volume");
		values[i++] = QT_TRANSLATE_NOOP("AbstractSetting", "Zooming");
	}

	virtual const char* getDescription(int i);

	void save();
	void load();
};

class ZoomLevel: public AbstractSetting {

private:
	static const int NUM = 99999;
	char buf[2];

public:

	ZoomLevel(QObject *parent = 0) :
		AbstractSetting("zoom-level", 1, NUM, parent) {

		setDefault(256);
	}

	virtual const char* getDescription(int i);

	void save();
	void load();
};

#endif /* SETTINGS_H_ */
